package top.zhangjianyong.blog.service.impl;

import com.aliyun.sts20150401.Client;
import com.aliyun.sts20150401.models.AssumeRoleRequest;
import com.aliyun.sts20150401.models.AssumeRoleResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import top.zhangjianyong.blog.config.OssProperties;
import top.zhangjianyong.blog.config.sts.StsProperties;
import top.zhangjianyong.blog.enums.StsOperationType;
import top.zhangjianyong.blog.factory.StsClientFactory;
import top.zhangjianyong.blog.model.request.StsTokenRequest;
import top.zhangjianyong.blog.model.response.StsTokenResponse;
import top.zhangjianyong.blog.service.StsService;
import top.zhangjianyong.blog.util.StsPolicyBuilder;

/**
 * STS 服务实现类
 * 使用阿里云 STS20150401 SDK 实现临时授权功能
 * 
 * @author zhangjianyong
 * @since 2024-01-01
 */
@Slf4j
@Service
public class StsServiceImpl implements StsService {

    @Autowired
    private StsProperties stsProperties;
    
    @Autowired
    private StsClientFactory stsClientFactory;
    
    @Autowired
    private OssProperties ossProperties;

    @Override
    public StsTokenResponse getStsToken(StsTokenRequest request) {
        try {
            log.info("开始获取STS Token，用户ID: {}, 操作类型: {}", request.getUserId(), request.getOperation());

            // 获取操作类型
            StsOperationType operationType = StsOperationType.fromCode(request.getOperation());
            
            // 构建权限策略
            String policy = buildPolicy(operationType, request);
            
            // 记录生成的策略内容（用于调试）
            log.info("生成的STS策略: {}", policy);
            
            // 创建AssumeRole请求
            AssumeRoleRequest assumeRoleRequest = new AssumeRoleRequest()
                    .setRoleArn(stsProperties.getRoleArn())
                    .setRoleSessionName(stsProperties.getRoleSessionName() + "-" + request.getUserId())
                    .setDurationSeconds(stsProperties.getDurationSeconds().longValue())
                    .setPolicy(policy);
            
            // 调用STS服务获取临时凭证
            Client client = stsClientFactory.getStsClient();
            AssumeRoleResponse response = client.assumeRole(assumeRoleRequest);
            
            // 构建响应
            StsTokenResponse tokenResponse = new StsTokenResponse();
            tokenResponse.setAccessKeyId(response.getBody().getCredentials().getAccessKeyId());
            tokenResponse.setAccessKeySecret(response.getBody().getCredentials().getAccessKeySecret());
            tokenResponse.setSecurityToken(response.getBody().getCredentials().getSecurityToken());
            tokenResponse.setExpiration(response.getBody().getCredentials().getExpiration());
            tokenResponse.setRegion("cn-hangzhou");
            tokenResponse.setPolicy(policy);

            log.info("STS Token获取成功，用户ID: {}", request.getUserId());
            return tokenResponse;

        } catch (Exception e) {
            log.error("获取STS Token失败，用户ID: {}, 错误信息: {}", request.getUserId(), e.getMessage(), e);
            throw new RuntimeException("获取STS Token失败: " + e.getMessage());
        }
    }

    @Override
    public boolean validateToken(String accessKeyId, String securityToken) {
        // 这里可以实现Token验证逻辑
        // 可以通过检查Token格式、过期时间等方式进行验证
        return accessKeyId != null && securityToken != null &&
            accessKeyId.startsWith("STS.") && !securityToken.isEmpty();
    }

    @Override
    public StsTokenResponse refreshToken(StsTokenRequest request) {
        // 刷新Token，实际就是重新获取
        return getStsToken(request);
    }

    /**
     * 构建权限策略
     * 使用策略构建器生成JSON格式的权限策略
     */
    private String buildPolicy(StsOperationType operationType, StsTokenRequest request) {
        // 从配置中获取存储桶名称和路径前缀
        String bucketName = ossProperties.getBucketName();
        String pathPrefix = ossProperties.getPathPrefix();
        
        // 验证配置
        if (bucketName == null || bucketName.isEmpty() || "your-bucket-name".equals(bucketName)) {
            throw new RuntimeException("OSS存储桶名称未正确配置，请在配置文件中设置正确的bucket-name");
        }
        
        log.info("构建STS策略，操作类型: {}, 存储桶: {}, 路径前缀: {}", 
                operationType.getCode(), bucketName, pathPrefix);
        
        // 如果有自定义路径，使用自定义路径
        if (request.getPath() != null && !request.getPath().isEmpty()) {
            return StsPolicyBuilder.buildCustomPolicy(operationType, bucketName, request.getPath());
        }
        
        // 使用默认路径前缀
        return StsPolicyBuilder.buildPolicy(operationType, bucketName, pathPrefix);
    }
} 